package drds.server.config.loader.xml;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import drds.server.config.cluster.ClusterConfig;
import drds.server.config.model.DRDS;
import drds.server.config.model.User;
import drds.server.config.util.ConfigException;
import drds.server.config.util.ConfigUtil;
import drds.server.config.util.ParameterMapping;

/**
 * 
 */
@SuppressWarnings("unchecked")
public class ServerLoader {
	private final DRDS drds;
	private final Map<String, User> userMap;
	private ClusterConfig clusterConfig;

	public ServerLoader() {
		this.drds = new DRDS();
		this.userMap = new HashMap<String, User>();
		this.load();
	}

	public DRDS getDRDS() {
		return drds;
	}

	public Map<String, User> getUserMap() {
		return (Map<String, User>) (userMap.isEmpty() ? Collections.emptyMap() : Collections.unmodifiableMap(userMap));
	}

	public ClusterConfig getClusterConfig() {
		return clusterConfig;
	}

	private void load() {
		// 读取server.xml配置
		InputStream dtd = null;
		InputStream xml = null;
		try {
			dtd = ServerLoader.class.getResourceAsStream("/server.dtd");
			xml = ServerLoader.class.getResourceAsStream("/server.xml");
			Element rootElement = ConfigUtil.getDocument(dtd, xml).getDocumentElement();

			// 加载System标签
			loadSystemLable(rootElement);

			// 加载User标签
			loadUsersLable(rootElement);

			// 加载集群配置
			this.clusterConfig = new ClusterConfig(rootElement, DRDS.DEFAULT_PORT);

		} catch (ConfigException e) {
			throw e;
		} catch (Exception e) {
			throw new ConfigException(e);
		} finally {
			if (dtd != null) {
				try {
					dtd.close();
				} catch (IOException e) {
				}
			}
			if (xml != null) {
				try {
					xml.close();
				} catch (IOException e) {
				}
			}
		}
	}

	private void loadUsersLable(Element rootElement) {
		NodeList userNodeList = rootElement.getElementsByTagName("user");
		for (int i = 0, length = userNodeList.getLength(); i < length; i++) {
			Node userNode = userNodeList.item(i);
			//
			if (userNode instanceof Element) {
				User user = new User();
				Element element = (Element) userNode;

				String name = element.getAttribute("name");
				//
				if (userMap.containsKey(name)) {
					throw new ConfigException("user " + name + " duplicated!");
				}
				user.setName(name);
				//
				Map<String, Object> property = ConfigUtil.loadElements(element);
				String password = (String) property.get("password");
				user.setPassword(password);
				//
				String benchmark = (String) property.get("benchmark");
				if (null != benchmark) {
					user.setBenchmark(Integer.parseInt(benchmark));
				}
				//
				String readOnly = (String) property.get("readOnly");
				if (null != readOnly) {
					user.setReadOnly(Boolean.parseBoolean(readOnly));
				}
				//
				userMap.put(name, user);
			}
		}
	}

	private void loadSystemLable(Element rootElement) throws IllegalAccessException, InvocationTargetException {
		NodeList systemNodeList = rootElement.getElementsByTagName("system");
		for (int i = 0, length = systemNodeList.getLength(); i < length; i++) {
			Node systemNode = systemNodeList.item(i);
			if (systemNode instanceof Element) {
				Map<String, Object> property = ConfigUtil.loadElements((Element) systemNode);
				ParameterMapping.mapping(drds, property);
			}
		}
	}

}
